package cn.song.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static cn.hutool.json.JSONUtil.toJsonStr;

/**
 * 工具类
 *
 * @author SongRenShuo
 * @date 2024/01/23
 */
@Slf4j
@Component
public class Tools {


    private static final String ADDRESS_PATTERN = "^([\u4e00-\u9fa5]{1,10}[自治区|省|市|特别行政区] [\u4e00-\u9fa5]{1,10}[自治州|市|盟|县|区] [\u4e00-\u9fa5]{1,20}[区|市|旗|寺|县|街道|乡|苏木|镇] [0-9|A-Z|a-z|\u4e00-\u9fa5| |（|）|-]{1,100})$";
    private static final String PHONE_PATTERN = "^[1][3,4,5,6,7,8,9][0-9]{9}$";

    /**
     * 地址格式校验
     *
     * @param address 地址
     * @return boolean
     * @date 2024/01/05
     * @author SongRenShuo
     */
    public static boolean isValidAddress(String address) {
        return Pattern.matches(ADDRESS_PATTERN, address);
    }

    /**
     * 手机号格式校验
     *
     * @param phone 手机号
     * @return boolean
     * @date 2024/01/05
     * @author SongRenShuo
     */
    public static boolean isValidPhone(String phone) {
        return Pattern.matches(PHONE_PATTERN, phone);
    }


    /**
     * 校验不发货地区或校验限制IP
     *
     * @param noAddress   需要限制的地址，多个地址之间用逗号分隔
     * @param takeAddress 需要验证的地址
     * @return 如果需要验证的地址不在noAddress列表中，则返回true；否则返回false
     */
    public static boolean checkGoodsNoAddress(String noAddress, String takeAddress) {
        // 如果限制地址为空或者长度为0，表示没有限制地址，直接返回true
        if (noAddress == null || noAddress.isEmpty()) {
            return true;
        }

        // 将限制地址按照逗号分割成字符串数组，并去除空字符串
        List<String> noAddressList = Arrays.stream(noAddress.split(","))
                .map(String::trim)
                .filter(str -> !str.isEmpty())
                .collect(Collectors.toList());

        // 遍历限制地址列表
        for (String restrictedArea : noAddressList) {
            // 如果需要验证的地址包含当前的限制地址
            if (takeAddress.contains(restrictedArea)) {
                // 返回false，表示需要验证的地址在限制地址列表中
                return false;
            }
        }

        // 如果循环结束都没有找到匹配的限制地址，返回true，表示需要验证的地址不在限制地址列表中
        return true;
    }


    /**
     * 获取当前登录账户 - bianma
     *
     * @param bianMa  编码
     * @param request 请求
     * @return {@link String }
     * @date 2024/01/22
     * @author SongRenShuo
     */
    public static String getZhangHu(String bianMa, HttpServletRequest request) {
        return getZhangHu00(bianMa, request, "bianma");
    }



    /**
     * 获取当前登录账户 - zhanghu
     *
     * @param zhangHu 账户
     * @param request 请求
     * @return {@link String }
     * @date 2024/01/22
     * @author SongRenShuo
     */
    public static String getZhangHu02(String zhangHu, HttpServletRequest request) {
        return getZhangHu00(zhangHu, request, "zhanghu");
    }

    /**
     * 获取当前登录账户 - mingcheng
     *
     * @param zhangHu 账户
     * @param request 请求
     * @return {@link String }
     * @date 2024/01/22
     * @author SongRenShuo
     */
    public static String getZhangHu03(String zhangHu, HttpServletRequest request) {
        return getZhangHu00(zhangHu, request, "mingcheng");
    }
    private static String getZhangHu00(String bianMa, HttpServletRequest request, String bianma) {
        try {

            if (StringUtils.isBlank(bianMa)) {
                String token = request.getHeader("token");
                bianMa = "";
                if (StringUtils.isNotBlank(token)) {
                    Map map = JavaWebToken.parserJavaWebToken(token);
                    if (map != null) {
                        bianMa = map.get(bianma).toString();
                    }
                }
            }
            return bianMa;
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 排序并拼接
     *
     * @param params 参数
     * @return {@link String }
     * @date 2024/03/21
     * @author SongRenShuo
     */
    public String createLinkString(Map<String, String> params) {
        log.info("排序前 = " + toJsonStr(params.toString()));
        List<Map.Entry<String, String>> list = new ArrayList<>(params.entrySet());
        // 然后通过比较器来实现排序
        // 升序排序
        list.sort(Map.Entry.comparingByKey());
        StringBuilder builder = new StringBuilder();
        for (Map.Entry<String, String> mapping : list) {
            builder.append(mapping.getKey()).append("=").append(mapping.getValue()).append("&");
        }
        String newStar = builder.substring(0, builder.length() - 1);
        log.info("拼接后 = " + newStar);
        return newStar;
    }

    /**
     * 文件上传
     *
     * @param file                文件
     * @param filePath            文件路径
     * @param customFileName      自定义文件名（不含后缀）
     * @param clearExistingFolder 是否清空已存在的文件夹
     * @return 支付平台证书地址
     * @author SongRenShuo
     */
    public static String getFileUpload(MultipartFile file, String filePath, String customFileName, boolean clearExistingFolder) {
        if (file != null) {

            // 获取原始文件名和后缀
            String originalFileName = file.getOriginalFilename();
            String fileExtension = null;
            if (originalFileName != null) {
                fileExtension = originalFileName.substring(originalFileName.lastIndexOf(".") + 1);
            }
            // 检查自定义文件名是否为空，若为空则使用原始文件名（不含路径和后缀）
            String fileNameToSave = customFileName.isEmpty() ? originalFileName : customFileName + "." + fileExtension;
            File dest = new File(filePath + fileNameToSave);
            // 如果需要清空已存在的文件夹
            if (clearExistingFolder && dest.getParentFile().exists()) {
                deleteDirectory(dest.getParentFile());
            }
            // 不存在就创建
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }
            try {
                // 保存文件
                long copy = Files.copy(file.getInputStream(), Paths.get(filePath + fileNameToSave), StandardCopyOption.REPLACE_EXISTING);
                // FilePath.yasuo(filePath,fileNameToSave);
                // 文件上传成功
                if (copy > 0) {
                    return fileNameToSave;
                }
            } catch (IOException e) {
                log.error("文件保存失败", e);
            }
        }
        return null;

    }


    /**
     * 删除目录
     *
     * @param directory 目录
     * @date 2023/12/28
     * @author SongRenShuo
     */
    public static void deleteDirectory(File directory) {
        if (directory.exists()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        deleteDirectory(file);
                    } else {
                        file.delete();
                    }
                }
            }
            directory.delete();
        }
    }

    /**
     * 下载文件
     *
     * @param path     路径
     * @param filename 文件名
     * @param response 响应
     * @throws IOException ioexception
     */
    public static void downfile(String path, String filename, HttpServletResponse response) throws IOException {
        System.err.println(filename + "==============");
        // 设置响应内容类型为下载
        response.setContentType("application/x-msdownload");
        // 设置响应头，使浏览器弹出下载框并提示下载文件名
        response.addHeader("Content-Disposition", "attachment;fileName=" + new String(filename.getBytes(), "iso8859-1"));
        // 获取输出流
        OutputStream os = response.getOutputStream();
        // 创建文件输入流
        FileInputStream fis = new FileInputStream(path);
        try {
            // 创建缓冲输入流
            BufferedInputStream bufferedInputStream = new BufferedInputStream(fis);
            // 创建缓冲输出流
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(os);
            // 创建缓冲区
            byte[] buffer = new byte[4096];
            int count = 0;
            // 循环读取文件内容到缓冲区
            while ((count = bufferedInputStream.read(buffer, 0, buffer.length)) > 0) {
                // 将缓冲区内容写入输出流
                bufferedOutputStream.write(buffer, 0, count);
            }
            bufferedInputStream.close(); // 关闭缓冲输入流
            bufferedOutputStream.flush(); // 刷新缓冲输出流
            bufferedOutputStream.close(); // 关闭缓冲输出流
            os.close(); // 关闭输出流
            fis.close(); // 关闭文件输入流
        } catch (Exception e) {
            e.printStackTrace(); // 打印异常信息
        }
    }


    /**
     * 每页显示的记录数
     */
    public static final Integer PAGE_SIZE = 20;


    /**
     * 发送POST请求并返回结果
     *
     * @param urlStr      请求的URL地址
     * @param param       请求的参数
     * @param ContentType 请求的内容类型，默认为application/x-www-form-urlencoded; charset=UTF-8
     * @return 返回服务器响应的结果
     */
    public static String sendPost(String urlStr, String param, String ContentType) {
        PrintWriter printWriter = null;
        BufferedReader reader = null;
        String result = "";
        try {
            // 创建一个URL对象
            URL url = new URL(urlStr);
            // 打开一个HttpURLConnection连接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 根据ContentType设置请求头
            if (ContentType == null) {
                conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            } else {
                conn.setRequestProperty("Content-Type", "application/json");
            }
            // 设置请求头的其他属性
            conn.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Shuame)");
            // 设置请求方法为POST
            conn.setRequestMethod("POST");
            // 允许输入输出
            conn.setDoInput(true);
            conn.setDoOutput(true);
            // 获取输出流并写入参数
            printWriter = new PrintWriter(conn.getOutputStream());
            printWriter.print(param);
            printWriter.flush();
            printWriter.close();
            // 获取输入流并读取响应内容
            reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
            String str = null;

            while ((str = reader.readLine()) != null) {
                result += str + "";
            }
            reader.close();
            // 打印请求信息
            System.err.println("url:" + urlStr + " param:" + param + " result:" + result);

        } catch (Exception e) {
            // 打印异常信息
            System.err.println("url:" + urlStr + " param:" + param);
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (printWriter != null) {
                    printWriter.close();
                }
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        // 返回结果
        return result;
    }

    /***
     * 获取 request 中 json 字符串的内容
     *
     * @param request
     * @return : <code>byte[]</code>
     * @throws IOException
     */
    public static String getRequestJsonString(HttpServletRequest request)
            throws IOException {
        String submitMehtod = request.getMethod();
        // GET
        if ("GET".equals(submitMehtod)) {
            return new String(request.getQueryString().getBytes("iso-8859-1"), "utf-8").replaceAll("%22", "\"");
            // POST
        } else {
            return getRequestPostStr(request);
        }
    }

    /**
     * 描述:获取 post 请求的 byte[] 数组
     * <pre>
     * 举例：
     * </pre>
     *
     * @param request
     * @return
     * @throws IOException
     */
    public static byte[] getRequestPostBytes(HttpServletRequest request)
            throws IOException {
        int contentLength = request.getContentLength();
        if (contentLength < 0) {
            return null;
        }
        byte[] buffer = new byte[contentLength];
        for (int i = 0; i < contentLength; ) {

            int readlen = request.getInputStream().read(buffer, i,
                    contentLength - i);
            if (readlen == -1) {
                break;
            }
            i += readlen;
        }
        return buffer;
    }

    /**
     * 描述:获取 post 请求内容
     * <pre>
     * 举例：
     * </pre>
     *
     * @param request
     * @return
     * @throws IOException
     */
    public static String getRequestPostStr(HttpServletRequest request)
            throws IOException {
        byte[] buffer = getRequestPostBytes(request);
        String charEncoding = request.getCharacterEncoding();
        if (charEncoding == null) {
            charEncoding = "UTF-8";
        }
        return new String(buffer, charEncoding);
    }

    /**
     * 加密方法，使用MD5算法对明文进行加密
     *
     * @param plainText 需要加密的明文字符串
     * @return 加密后的密文字符串
     */
    public static String encryption(String plainText) {
        String re_md5 = new String();
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(plainText.getBytes());
            byte[] b = md.digest();

            int i;

            StringBuffer buf = new StringBuffer("");
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0) {
                    i += 256;
                }
                if (i < 16) {
                    buf.append("0");
                }
                buf.append(Integer.toHexString(i));
            }

            re_md5 = buf.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return re_md5;
    }


    /**
     * 将给定的浮点数保留三位小数并四舍五入
     *
     * @param d 需要处理的浮点数
     * @return 保留三位小数后的浮点数
     */
    public static double getThreeDecimal(double d) {
        BigDecimal b = new BigDecimal(d);
        return d = b.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue();
    }


}
